package com.fjut.zr.judge_system.OJ.OJS;


import java.io.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class CppLanguage extends BaseOJ{

    @Override
    public void run() {
        //获取输入文件目录
        language="C++";
        try {
            List<String> inlist = getInList(data + pid);
            //编译
            complie(code, pid, rid);
            //运行代码
            String runresult = run(rid, pid, inlist, time, memory);
            System.out.println(runresult);
            if (runresult.equals("Complie Success") == true) {
                System.out.println("第" + rid + "次提交：文件比对开始");
                List<String> outlist = getOutList(data + pid);
                double score=judge(rid, pid, outlist);
                submitResult.setScore(score);
                if(score<100)
                {
                    submitResult.setResult("Wrong Answer");
                }
                else
                {
                    submitResult.setResult("Accepted");
                }
                submitResult.setTime(maxtime);
                submitResult.setMemory(maxmemory);
                System.out.println("第" + rid + "次提交结果\n"+submitResult.toString());
            }
            else
            {
                submitResult.setResult(runresult);
            }
            returnResult();
        }  catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void mkTemporaryDirs(File file) {
        // 判断上一级文件夹是否存在
        if (!file.getParentFile().exists()) {
            // 不存在则生成一个
            file.getParentFile().mkdirs();
            System.out.println("C++语言创建文件夹成功");
        }
        // 判断文件是否存在
        if (!file.exists()) {
            try {
                // 不存在则创建一个
                file.createNewFile();
                System.out.println("第一次创建文件成功");
            } catch (IOException e) {
                System.out.println("第一次创建文件失败");
                e.printStackTrace();
            }
        }
    }

    @Override
    public void complie(String code, String pid, String rid) throws IOException {
        String filepath=run+rid+"/code/Main.cpp";
        String resultpath=run+rid+"/result/1.out";
        File codefile=new File(filepath);
        File resultfile=new File(resultpath);
        //创建代码文件
        mkTemporaryDirs(codefile);
        //创建结果文件夹
        mkTemporaryDirs(resultfile);
        //写入代码文件
        inputStreamToFile(code,codefile);
        //生成a.out文件
        doOrder("g++ "+filepath+" -o "+run+rid+"/code/a.out");
    }

    @Override
    public String runcode(String rid, String pid, String infile, int time, int memory) {
        double total,free;
        long start=0,end=0;
        int usetime=0,use=0;
        String runcmd=run+rid+"/code/a.out < "+data+pid+"/"+infile+" > "+run+rid+"/result/"+infile.substring(0,infile.length()-3)+".out";
        Runtime run = Runtime.getRuntime();
        try {
            start= System.currentTimeMillis();
            Process process = run.exec(new String[]{"/bin/sh","-c",runcmd});
            end=System.currentTimeMillis();
            usetime=(int)(end-start);
            //Java 虚拟机中的内存总量,以字节为单位
            total = (int)Runtime.getRuntime().totalMemory()/1024.0;
            //Java 虚拟机中的空闲内存量
            free = (int)Runtime.getRuntime().freeMemory()/1024.0;
            use=(int)(total-free);
            // 标准输入流（必须写在 waitFor 之前）
            String inStr = consumeInputStream(process.getInputStream());
            // 标准错误流（必须写在 waitFor 之前）
            String errStr = consumeInputStream(process.getErrorStream());
            if(process.waitFor(time, TimeUnit.MILLISECONDS)==false)
            {
                process.destroy();
                return "Time Limit Exceeded";
            }
            if(use>memory)
            {
                process.destroy();
                return "Memory Limit Exceeded";
            }
            if(errStr.length()!=0)
            {
                submitResult.setErrorinfo(errStr);
                process.destroy();
                return "Runtime Error";
            }
            process.destroy();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(usetime>maxtime)
        {
            maxtime=usetime;
        }
        if(use>maxmemory)
        {
            maxmemory=use;
        }
        return "Complie Success";
    }
}
